package com.kangda.verify;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;

import androidx.appcompat.widget.AppCompatEditText;

import com.kangda.parttitionstorage.R;

import java.util.Timer;
import java.util.TimerTask;

/**
 * @Author Kang da
 * @Date 2020-02-14 17:48
 */
public class VerifyCodeEditText extends AppCompatEditText {
    public VerifyCodeEditText(Context context) {
        super(context);
        init(context, null);
    }

    public VerifyCodeEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    public VerifyCodeEditText(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

    private int mFigures;// 验证码个数
    private int mCodeMargin;// 验证码之间的间距
    private int mSelectColor;// 选中框的颜色
    private int mNormalColor;// 普通框的颜色
    private float mBorderRadius;// 边框直角的曲度
    private float mBorderWidth;// 边框的厚度
    private float mCursorWidth;// 光标宽度
    private int mCursorColor;// 光标的颜色
    private long mCursorDuration;// 光标闪烁的时间


    private OnVerifyCodeChangedListener onVerifyCodeChangedListener;
    private int mCurrentPosition = 0;// 当前验证码的位置
    private int mEachRectLength = 0;// 矩形边长
    private Paint mNormalPaint = new Paint();
    private Paint mSelectPaint = new Paint();
    private Paint mCursorPaint = new Paint();
    private Paint mBGPaint = new Paint();
    private int DEFAULT_CURSOR_DURATION = 400;

    // 控制光标闪烁
    private boolean isCursorShowing = false;
    private TimerTask mCursorTimerTask;
    private Timer mCursorTimer;

    public void init(Context context, AttributeSet attrs) {
        initAttr(context, attrs);
        initPaint();
        initCursorTimer();
        setFocusableInTouchMode(true);
        initTextChangedListener();
    }

    private void initAttr(Context context, AttributeSet attrs) {
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.VerifyCodeEditText);
        mFigures = ta.getInteger(R.styleable.VerifyCodeEditText_vce_figures, 6);
        mCodeMargin = (int) ta.getDimension(R.styleable.VerifyCodeEditText_vce_codeMargin, 0f);
        mSelectColor = ta.getColor(R.styleable.VerifyCodeEditText_vce_selectBorderColor, getCurrentTextColor());
        mNormalColor = ta.getColor(R.styleable.VerifyCodeEditText_vce_normalBorderColor, getResources().getColor(android.R.color.darker_gray,null));
        mBorderRadius = ta.getDimension(R.styleable.VerifyCodeEditText_vce_borderRadiusSize, 6f);
        mBorderWidth = ta.getDimension(R.styleable.VerifyCodeEditText_vce_borderWidth, 1f);
        mCursorWidth = ta.getDimension(R.styleable.VerifyCodeEditText_vce_cursorWidth, 1f);
        mCursorColor = ta.getColor(R.styleable.VerifyCodeEditText_vce_cursorColor, getResources().getColor(android.R.color.darker_gray,null));
        mCursorDuration = ta.getInteger(R.styleable.VerifyCodeEditText_vce_cursorDuration, DEFAULT_CURSOR_DURATION);
        ta.recycle();
        setLayoutDirection(LAYOUT_DIRECTION_LTR);
    }


    private void initPaint() {
        mNormalPaint.setAntiAlias(true);
        mNormalPaint.setColor(mNormalColor);
        mNormalPaint.setStyle(Paint.Style.STROKE);
        mNormalPaint.setStrokeWidth(mBorderWidth);

        mSelectPaint.setAntiAlias(true);
        mSelectPaint.setColor(mSelectColor);
        mSelectPaint.setStyle(Paint.Style.STROKE);
        mSelectPaint.setStrokeWidth(mBorderWidth);

        mCursorPaint.setAntiAlias(true);
        mCursorPaint.setColor(mCursorColor);
        mCursorPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        mCursorPaint.setStrokeWidth(mCursorWidth);

        mBGPaint.setAntiAlias(true);
        mBGPaint.setColor(getResources().getColor(R.color.gray_eb,null));
        mBGPaint.setStyle(Paint.Style.FILL);
    }


    private void initCursorTimer() {
        mCursorTimerTask = new TimerTask() {
            @Override
            public void run() {
                isCursorShowing = !isCursorShowing;
                postInvalidate();
            }
        };
        mCursorTimer = new Timer();
    }


    private void initTextChangedListener() {
        addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
                if (getText() != null) {
                    mCurrentPosition = getText().length();
                }
                postInvalidate();
            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                if (getText() != null) {
                    mCurrentPosition = getText().length();
                }
                postInvalidate();
                onVerifyCodeChangedListener.onVerCodeChanged(getText(), start, before, count);
            }

            @Override
            public void afterTextChanged(Editable s) {
                if (getText() != null) {
                    mCurrentPosition = getText().length();
                    postInvalidate();
                    if (getText().length() == mFigures) {
                        onVerifyCodeChangedListener.onInputCompleted(getText());
                    } else if (getText().length() > mFigures) {
                        getText().delete(mFigures, getText().length());
                    }
                }
            }
        });
    }

    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthResult = 0;
        int heightResult = 0;

        int widthMode = View.MeasureSpec.getMode(widthMeasureSpec);
        int widthSize = View.MeasureSpec.getSize(widthMeasureSpec);
        if (widthMode == View.MeasureSpec.EXACTLY) {
            widthResult = widthSize;
        } else {
            widthResult = getScreenWidth(getContext());
        }
        // 每个矩形的宽度
        mEachRectLength = View.MeasureSpec.getSize(heightMeasureSpec);

        int heightMode = View.MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = View.MeasureSpec.getSize(heightMeasureSpec);
        if (heightMode == View.MeasureSpec.EXACTLY) {
            heightResult = heightSize;
        } else {
            heightResult = mEachRectLength;
        }
        setMeasuredDimension(widthResult, heightResult);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                requestFocus();
                if (getText() != null) {
                    setSelection(getText().length());
                }
                showKeyBoard(getContext());
                return false;
        }
        return super.onTouchEvent(event);
    }

    @SuppressLint("DrawAllocation")
    public void onDraw(Canvas canvas) {
        if (getText() != null) {
            mCurrentPosition = getText().length();
        }
        int width = mEachRectLength - getPaddingLeft() - getPaddingRight();
        int height = getMeasuredHeight() - getPaddingTop() - getPaddingBottom();
        for (int i = 0; i < mFigures; i++) {
            float start = width * i + mCodeMargin * i + mBorderWidth;
            float end = start + width - mBorderWidth;
            RectF bgRect = new RectF(start, mBorderWidth, end, height - mBorderWidth);
            canvas.save();
            canvas.drawRoundRect(bgRect, mBorderRadius, mBorderRadius, mBGPaint);
            if (i == mFigures - 1) {
                end -= mBorderWidth;
            }
            RectF rect = new RectF(start, mBorderWidth, end, height - mBorderWidth);
            // 画矩形选框
            if (i == mCurrentPosition) {//选中的下一个状态
                canvas.drawRoundRect(rect, mBorderRadius, mBorderRadius, mSelectPaint);
            } else {
                canvas.drawRoundRect(rect, mBorderRadius, mBorderRadius, mNormalPaint);
            }
            canvas.restore();
        }

        // 绘制文字
        String value = getText().toString();
        for (int i = 0; i < value.length(); i++) {
            canvas.save();
            float start = width * i + mCodeMargin * i;
            float x = start + width / 2f;
            getPaint().setTextAlign(Paint.Align.CENTER);
            getPaint().setColor(getCurrentTextColor());
            Paint.FontMetrics fontMetrics = getPaint().getFontMetrics();
            float baseline = (height - fontMetrics.bottom + fontMetrics.top) / 2 - fontMetrics.top;
            canvas.drawText(String.valueOf(value.toCharArray()[i]), x, baseline, getPaint());
            canvas.restore();
        }

        // 绘制光标
        if (!isCursorShowing && isCursorVisible() && mCurrentPosition < mFigures && hasFocus()) {
            canvas.save();
            float startX = (width + mCodeMargin) * mCurrentPosition + width / 2f;
            float startY = height / 4f;
            float endX = startX;
            float endY = height - height / 4f;
            canvas.drawLine(startX, startY, endX, endY, mCursorPaint);
            canvas.restore();
        }

    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        // 启动定时任务，定时刷新实现光标闪烁
        mCursorTimer.scheduleAtFixedRate(mCursorTimerTask, 0, mCursorDuration);
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        mCursorTimer.cancel();
        mCursorTimer = null;
    }

    private int getScreenWidth(Context context) {
        DisplayMetrics metrics = new DisplayMetrics();
        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        wm.getDefaultDisplay().getMetrics(metrics);
        return metrics.widthPixels;
    }

    private void showKeyBoard(Context context) {
        InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.showSoftInput(this, InputMethodManager.SHOW_FORCED);
    }

    public void setVerifyCodeChangedListener(OnVerifyCodeChangedListener verifyCodeChangedListener){
        this.onVerifyCodeChangedListener = verifyCodeChangedListener;
    }

    /**
     * 验证码变化时候的监听事件
     */
    public interface OnVerifyCodeChangedListener {
        /**
         * 当验证码变化的时候
         */
        public void onVerCodeChanged(CharSequence s, int start, int before, int count);

        /**
         * 输入完毕后的回调
         */
        public void onInputCompleted(CharSequence s);
    }
}
